/*Filipe Augusto de Souza Fragoso  Nusp - 7277454*/

/*ALGORITMO SEQUENCIAL DE GAUSS LENGENDRE PARA APROXIMACAO DO VALOR DO PI*/

#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <gmp.h>
#define DIGITOS 10000000   // precisao - numero de casas do pi que sera salvo
#define IT 23   //numero de iteracoes do algoritmo (sao necessarias 23 iteracoes para se atingir a precisao de 10milhoes de digitos)


int main(int argc, char *argv[])
{
	/* DECLARACAO DE VARIAVEIS */	
    	time_t ini = time(0);		
	/* declaracao de variaveis GMP . Nro IT + 1 de casas devido a (inicializacao + nro de iteracoes ) */
    	mpf_t a[IT+1],b[IT+1],t[IT+1],p[IT+1],pi[IT+1],aux1,aux2;
    	int i = 0;
	
	/*definicao da precisao*/
	mpf_set_default_prec((DIGITOS*4)+16);

	/*inicializacao de variaveis e atribuicao de valores iniciais*/
	mpf_init(aux1);
	mpf_init(aux2);


 	mpf_init_set_ui(a[0], 1);      //valor inicial de a = 1

	mpf_init_set_ui(b[0], 1);      //valor inicial de b = 1/ sqrt(2)
	mpf_sqrt_ui(aux1, 2);   	
	mpf_div(b[0],b[0],aux1);	

	mpf_init_set_d(t[0], 0.25);   //valor inicial de t = 0.25
	
	mpf_init_set_ui(p[0], 1);      //valor inicial de p = 1

	mpf_init_set_ui(pi[0], 0);     //valor inicial de pi = 0


	/*ITERACOES*/
    	while(i<IT)
    	{	
		/* inicializacao das variaveis do tipo GMP na posicao i+1 dos vetores*/
		mpf_init(a[i+1]);
		mpf_init(b[i+1]);	
		mpf_init(t[i+1]);
		mpf_init(p[i+1]);
		mpf_init(pi[i+1]);

		//caculo corresponde a a[i+1]		
		mpf_add(aux1,a[i],b[i]);
      		mpf_div_ui(aux1, aux1,2);       //a[i+1] = ( a[i] + b[i] ) / 2;
      		mpf_set(a[i+1], aux1);
 	
		//caculo corresponde a b[i+1]		
      		mpf_mul(aux1,a[i],b[i]);        //b[i+1] = sqrt( a[i] * b[i]);
      		mpf_sqrt(b[i+1], aux1);   	
     
		//caculo corresponde a t[i+1]	
     		mpf_sub(aux1,a[i],a[i+1]);      //t[i+1] = t[i] - ( p[i] * ( pow( a[i] - a[i+1], 2 ) ) );
      		mpf_pow_ui (aux1,aux1,2);	
      		mpf_mul(aux2,p[i],aux1);
      		mpf_sub(t[i+1],t[i],aux2); 

		//caculo corresponde a p[i+1]		
      		mpf_mul_ui(p[i+1],p[i],2);	     //p[i+1] = 2 * p[i];     
     
		//caculo corresponde a pi[i+1]		
      		mpf_add(aux1,a[i],b[i]);   
      		mpf_pow_ui (aux1,aux1,2);       // pi[i+1] =  pow(a[i]+ b[i],2)/(4 * t[i]);
      		mpf_mul_ui(aux2,t[i],4); 
      		mpf_div(pi[i+1],aux1,aux2);    

     		i++; 
    	}

	/* calcula o tempo de execucao do algoritmo */
	int tempo_d = time(0)-ini;  	
	/* imprime o tempo de execucao do algoritmo */
	printf("tempo de execucao:%dsegs",tempo_d);
	/* tempo de execucao eh calculado antes de escrever o valor de pi no arquivo para saber-se 
	somente o tempo de execucao do algoritmo de Gauss Lengendre*/
	
	/* ponteiro para o arquivo*/
	FILE *fp;	

	fp = fopen ("exit.txt", "w");
	
	/* verifica se arquivo foi aberto com sucesso */
	if(fp == NULL)
	{
		printf("\n Erro de arquivo \n");
	}

	else 
	{
	/* escreve o valor de pi com 10milhoes de casas de precisao no arquivo apontado por fp */
	mpf_out_str(fp,10,(DIGITOS*4)+16, pi[i]);	
	fclose(fp);
	}
   
  	
	return 0;
}

